package com.cet.qz.unit01.chapter1_2.stream;

import java.security.SecureRandom;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: algorithm
 * @description:
 * @author: 陈恩涛
 * @create: 2021-01-13 16:29
 **/
public class StreamTest {

    public static void main(String[] args) {

        //为集合创建串行流
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");

        //为集合创建并行流
        List<String> filtered = strings.parallelStream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

        for (String s : filtered) {
            System.out.println(s);
        }
        System.out.println("======================");

        SecureRandom random = new SecureRandom();
        random.ints().limit(10).forEach(System.out::println);

        System.out.println("======================");
        List<Integer> numbers = Arrays.asList(3, 2, 4, 3, 7, 3, 5);
        //获取对应的平方数
        List<Integer> squaresList = numbers.stream().map(i -> i * i).distinct()
                .collect(Collectors.toList());
        for (Integer i : squaresList) {
            System.out.println(i);
        }

        System.out.println("==============");
        List<String> strings1 = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
        long count = strings1.stream().filter(string -> string.isEmpty()).count();
        System.out.println(count);

        System.out.println("===============");
        SecureRandom random1 = new SecureRandom();
        random1.ints().limit(10).sorted().forEach(System.out::println);

        System.out.println("===============");
        List<String> strings2 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        List<String> filtered2 = strings2.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

        System.out.println("筛选列表: " + filtered2);
        String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
        System.out.println("合并字符串: " + mergedString);

        System.out.println("===============");
        List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 8, 7, 4, 3, 2);
        //获取简要的统计信息
        IntSummaryStatistics stats = numberList.stream().mapToInt(x -> x).summaryStatistics();
        System.out.println("列表中最大的值为："+ stats.getMax());
        System.out.println("列表中最小的值为：" + stats.getMin());
        System.out.println("列表中数的总和为："+ stats.getSum());
        System.out.println("列表中数的平均值为：" + stats.getAverage());

        System.out.println("===============");
        //自定义排序
        Student s1 = new Student("aa", 10);
        Student s2 = new Student("bb", 20);
        Student s3 = new Student("cc", 30);
        Student s4 = new Student("dd", 10);
        List<Student> studentList = Arrays.asList(s1, s2, s3, s4);

        //自定义排序：先按姓名升序，姓名相同则按年龄升序
        List<Student> collect = studentList.stream().sorted(
                (o1, o2) -> {
                    if (o1.getName().equals(o2.getName())) {
                        return o1.getAge() - o2.getAge();
                    } else {
                        return o1.getName().compareTo(o2.getName());
                    }
                }
        ).collect(Collectors.toList());
        for (Student student : collect) {
            System.out.println(student.toString());
        }

        System.out.println("===============");
        //studentList.stream().peek(o -> o.setAge(100)).forEach(System.out::println);

        System.out.println("===============");
        List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
        boolean allMatch = ints.stream().allMatch(e -> e > 3);//false
        System.out.println(allMatch);
        boolean noneMatch = ints.stream().noneMatch(e -> e > 10);//true
        System.out.println(noneMatch);
        boolean anyMatch = ints.stream().anyMatch(e -> e > 6);//true
        System.out.println(anyMatch);

        Integer first = ints.stream().findFirst().get();//findFirst返回一个可选值数组,这里为第一个值
        System.out.println(first);//1
        Integer any = ints.stream().findAny().get();//1，串行流式有序的，第一个元素
        System.out.println(any);
        any = ints.parallelStream().findAny().get();//并行流没有顺序，得到不确定的元素
        System.out.println(any);

        long count1 = ints.stream().count();
        Integer max = ints.stream().max(Integer::compareTo).get();
        System.out.println(max);
        Integer min = ints.stream().min(Integer::compareTo).get();
        System.out.println(min);

        System.out.println("=====================");

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,13);

        Integer result = list.stream().reduce((x1, x2) ->
            x1 + x2
        ).get();
        System.out.println(result);
        result = list.stream().reduce(10, (x1, x2) -> x1 + x2);
        System.out.println(result);
        result = list.stream().reduce(0,
                (x1, x2) -> {
                    System.out.println("stream accumulator: x1:" + x1 + "  x2:" + x2);
                    return x1 - x2;
                },
                (x1, x2) -> {
                    System.out.println("stream combiner: x1:" + x1 + "  x2:" + x2);
                    return x1 * x2;
                });
        System.out.println(result);//-300

        //经过测试，当元素个数小于24时，并行时线程数等于元素个数，当大于等于24时，并行时线程数为16
        result = list.parallelStream().reduce(0,
                (x1, x2) -> {
                    System.out.println("stream accumulator: x1:" + x1 + "  x2:" + x2);
                    return x1 - x2;
                },
                (x1, x2) -> {
                    System.out.println("stream combiner: x1:" + x1 + "  x2:" + x2);
                    return x1 * x2;
                });
        System.out.println(result);//197474048

        System.out.println("================");

        //装成List
        List<Integer> ageList = studentList.stream().map(Student::getAge).collect(Collectors.toList());
        ageList.stream().forEach(System.out::println);

        //装成set
        Set<Integer> ageSet = studentList.stream().map(Student::getAge).collect(Collectors.toSet());
        ageSet.stream().forEach(System.out::println);

        //装成map，注意key不能相同，否则会报错
        Map<String, Integer> map = studentList.stream().collect(Collectors.toMap(Student::getName, Student::getAge));

        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
            System.out.println(entry.getKey()+":"+entry.getValue());
        }

        //字符串分隔符连接
        String joinName = studentList.stream().map(Student::getName).collect(Collectors.joining(",", "(", ")"));
        System.out.println(joinName);

        //聚合操作
        //学生总数
        Long counts = studentList.stream().collect(Collectors.counting());
        System.out.println(counts);
        //最大年龄
        Integer maxAge = studentList.stream().map(Student::getAge).collect(Collectors.maxBy(Integer::compareTo)).get();
        System.out.println(maxAge);
        //年龄总和
        Integer sumAge = studentList.stream().collect(Collectors.summingInt(Student::getAge));
        System.out.println(sumAge);
        //平均年龄
        Double avgAge = studentList.stream().collect(Collectors.averagingInt(Student::getAge));
        System.out.println(avgAge);

        //一次性获取统计信息
        DoubleSummaryStatistics statistics = studentList.stream().collect(Collectors.summarizingDouble(Student::getAge));
        System.out.println("学生总数：" + statistics.getCount() + ",学生最大年龄：" + statistics.getMax() + "，学生年龄总和：" + statistics.getSum() + ",学生平均年龄：" + statistics.getAverage());

        //分组
        Map<Integer, List<Student>> ageMap = studentList.stream().collect(Collectors.groupingBy(Student::getAge));
        System.out.println(ageMap);

        //多重分组,先根据类型分再根据年龄分
        //Map<Integer, Map<Integer, List<Student>>> typeAgeMap = list.stream().collect(Collectors.groupingBy(Student::getType, Collectors.groupingBy(Student::getAge)));


        Map<Boolean, List<Student>> partMap = studentList.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 10));
        System.out.println(partMap);


    }


}
